package org.cybzacg.convert.converters.essential;


import lombok.extern.slf4j.Slf4j;
import org.cybzacg.convert.annotation.Converter;
import org.cybzacg.convert.constants.BoolDefaults;
import org.cybzacg.convert.context.ConversionContext;
import org.cybzacg.convert.core.AbstractTypeConverter;
import org.cybzacg.convert.enums.ConversionPriority;
import org.cybzacg.convert.enums.ConversionType;
import org.cybzacg.convert.exception.ConversionException;

import java.util.Set;

/**
 * 布尔类型转换器
 * 专门处理布尔类型的转换
 *
 * @author cybzacg.blog
 * @version 3.0
 * @since 3.0
 */
@Slf4j
@Converter(
    name = "BooleanConverter",
    priority = ConversionPriority.ESSENTIAL,
    description = "布尔类型转换器，处理各种类型到布尔值的转换",
    enabled = true,
    version = "3.0",
    author = "cybzacg.blog",
    supportedTypes = {Boolean.class, boolean.class},
    tags = {"boolean", "basic", "conversion"}
)
public class BooleanConverter extends AbstractTypeConverter {

    /**
     * 布尔值真值集合
     */
    private static final Set<String> TRUE_VALUES = BoolDefaults.TRUE_VALUES;

    /**
     * 布尔值假值集合
     */
    private static final Set<String> FALSE_VALUES = BoolDefaults.FALSE_VALUES;

    public BooleanConverter() {
        super(ConversionPriority.ESSENTIAL);
        log.debug("BooleanConverter 初始化完成，优先级: {}", ConversionPriority.ESSENTIAL);
    }

    @Override
    protected ConversionType getConversionType() {
        return ConversionType.BOOLEAN;
    }

    @Override
    @SuppressWarnings("unchecked")
    protected <T> T doConvert(Object source, Class<T> targetType, T defaultValue, ConversionContext context)
            throws Exception {

        log.debug("开始布尔类型转换: 源类型={}, 目标类型={}, 默认值={}",
                 source != null ? source.getClass().getSimpleName() : "null",
                 targetType.getSimpleName(),
                 defaultValue);

        if (source == null) {
            return defaultValue;
        }

        // 如果已经是布尔类型，直接返回
        if (source instanceof Boolean) {
            log.debug("源对象已经是布尔类型，直接返回: {}", source);
            return (T) source;
        }

        // 如果是基本类型boolean
        if (source.getClass() == boolean.class) {
            Boolean result = (boolean) source;
            log.debug("基本类型boolean转换: {} -> {}", source, result);
            return (T) result;
        }

        // 转换为布尔值
        Boolean result = convertToBoolean(source, context);
        log.debug("布尔类型转换完成: {} -> {}", source, result);

        return (T) result;
    }

    /**
     * 将对象转换为布尔值
     *
     * @param source 源对象
     * @param context 转换上下文
     * @return 布尔值
     * @throws ConversionException 转换失败时抛出
     */
    protected Boolean convertToBoolean(Object source, ConversionContext context) throws ConversionException {
        log.debug("开始将对象转换为布尔值: 源类型={}", source != null ? source.getClass().getSimpleName() : "null");

        if (source == null) {
            log.debug("源对象为null，返回false");
            return Boolean.FALSE;
        }

        Boolean result;

        // 字符串转换
        if (source instanceof String) {
            result = convertStringToBoolean((String) source);
            log.debug("字符串转换结果: '{}' -> {}", source, result);
            return result;
        }

        // 数值转换
        if (source instanceof Number number) {
            result = convertNumberToBoolean(number);
            log.debug("数值转换结果: {} -> {}", source, result);
            return result;
        }

        // 字符转换
        if (source instanceof Character) {
            result = convertCharToBoolean((Character) source);
            log.debug("字符转换结果: '{}' -> {}", source, result);
            return result;
        }

        // 其他类型，根据非空判断
        result = convertObjectToBoolean(source);
        log.debug("对象转换结果: {} -> {}", source.getClass().getSimpleName(), result);
        return result;
    }

    /**
     * 转换字符串为布尔值
     *
     * @param str 字符串
     * @return 布尔值
     */
    protected Boolean convertStringToBoolean(String str) {
        if (str == null) {
            return Boolean.FALSE;
        }

        String trimmed = str.toLowerCase().trim();

        if (TRUE_VALUES.contains(trimmed)) {
            return Boolean.TRUE;
        }

        if (FALSE_VALUES.contains(trimmed)) {
            return Boolean.FALSE;
        }

        // 尝试解析为数字
        try {
            double num = Double.parseDouble(trimmed);
            return num != 0;
        } catch (NumberFormatException e) {
            // 不是数字，根据字符串长度判断
            return !str.isEmpty();
        }
    }

    /**
     * 转换数值为布尔值
     *
     * @param number 数值
     * @return 布尔值
     */
    protected Boolean convertNumberToBoolean(Number number) {
        if (number == null) {
            return Boolean.FALSE;
        }

        return number.doubleValue() != 0;
    }

    /**
     * 转换字符为布尔值
     *
     * @param ch 字符
     * @return 布尔值
     */
    protected Boolean convertCharToBoolean(Character ch) {
        if (ch == null) {
            return Boolean.FALSE;
        }

        // 常见的布尔字符
        return switch (Character.toLowerCase(ch)) {
            case 't', 'y', '1', '是', '真', '开' -> Boolean.TRUE;
            case 'f', 'n', '0', '否', '假', '关' -> Boolean.FALSE;
            default ->
                // 其他字符，根据ASCII值判断
                    ch != '\0';
        };
    }

    /**
     * 转换对象为布尔值
     *
     * @param obj 对象
     * @return 布尔值
     */
    protected Boolean convertObjectToBoolean(Object obj) {
        if (obj == null) {
            return Boolean.FALSE;
        }

        // 集合类型：非空即为true
        if (obj instanceof java.util.Collection) {
            return !((java.util.Collection<?>) obj).isEmpty();
        }

        // Map类型：非空即为true
        if (obj instanceof java.util.Map) {
            return !((java.util.Map<?, ?>) obj).isEmpty();
        }

        // 数组类型：长度大于0即为true
        if (obj.getClass().isArray()) {
            if (obj instanceof Object[]) {
                return ((Object[]) obj).length > 0;
            } else if (obj instanceof int[]) {
                return ((int[]) obj).length > 0;
            } else if (obj instanceof long[]) {
                return ((long[]) obj).length > 0;
            } else if (obj instanceof double[]) {
                return ((double[]) obj).length > 0;
            } else if (obj instanceof boolean[]) {
                return ((boolean[]) obj).length > 0;
            } else if (obj instanceof byte[]) {
                return ((byte[]) obj).length > 0;
            } else if (obj instanceof short[]) {
                return ((short[]) obj).length > 0;
            } else if (obj instanceof float[]) {
                return ((float[]) obj).length > 0;
            } else if (obj instanceof char[]) {
                return ((char[]) obj).length > 0;
            }
        }

        // 其他对象，非null即为true
        return Boolean.TRUE;
    }

    @Override
    public boolean supports(Class<?> targetType) {
        return targetType == Boolean.class || targetType == boolean.class;
    }

    @Override
    public Class<?> getSupportedType() {
        return Boolean.class;
    }

    /**
     * 检查是否为真值字符串
     *
     * @param str 字符串
     * @return 是否为真值
     */
    public static boolean isTrueValue(String str) {
        if (str == null) {
            return false;
        }
        return TRUE_VALUES.contains(str.toLowerCase().trim());
    }

    /**
     * 检查是否为假值字符串
     *
     * @param str 字符串
     * @return 是否为假值
     */
    public static boolean isFalseValue(String str) {
        if (str == null) {
            return false;
        }
        return FALSE_VALUES.contains(str.toLowerCase().trim());
    }

    /**
     * 获取所有真值
     *
     * @return 真值集合
     */
    public static Set<String> getTrueValues() {
        return Set.copyOf(TRUE_VALUES);
    }

    /**
     * 获取所有假值
     *
     * @return 假值集合
     */
    public static Set<String> getFalseValues() {
        return Set.copyOf(FALSE_VALUES);
    }
}
